home *** CD-ROM | disk | FTP | other *** search
/ Aminet 30 / Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso / Aminet / hard / hack / i2clib40.lha / i2clib40 / src / I2CScan.c < prev    next >
C/C++ Source or Header  |  1998-08-24  |  9KB  |  273 lines

  1. /*========================================================================*\
  2.  |  File: I2CScan.c                                    Date: 24 Aug 1998  |
  3.  *------------------------------------------------------------------------*
  4.  |  Look who's listening on the I²C bus, using i2c.library                |
  5.  |  Usage:                                                                |
  6.  |    I2CScan [options]                                                   |
  7.  |  where options are:                                                    |
  8.  |  -d<delay> : adjust i2c.library's timing parameter                     |
  9.  |  -v : verbose, try to identify the listening chips by their addresses  |
  10.  |  -l : lock, force i2c.library to release its hardware                  |
  11.  |  -w : watch the statistics counters (only with lib version 40+)        |
  12.  |  Return values:                                                        |
  13.  |   0 = OK                                                               |
  14.  |   5 = no listeners detected                                            |
  15.  |  10 = scan failed due to resource allocation problems                  |
  16.  |  15 = errors occured which might indicate a hardware problem           |
  17.  |  20 = library not found                                                |
  18.  |                                                                        |
  19. \*========================================================================*/
  20.  
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <signal.h>
  25. #include <proto/exec.h>
  26. #include <proto/i2c.h>
  27. #include <libraries/i2c.h>
  28.  
  29. struct Library *I2C_Base = NULL;
  30.  
  31. struct chip
  32.     {
  33.     UBYTE lower_addr, upper_addr;
  34.     STRPTR description;
  35.     };
  36.  
  37. struct chip chiptab[] =
  38.     {
  39.     { 0x20, 0x20, "PCF8200: speech synthesizer" },
  40.     { 0x22, 0x22, "SAA5243/SAA5246: teletext decoder" },
  41.     { 0x20, 0x22, "SAF1135/SAA4700: VPS decoder" },
  42.     { 0x40, 0x4E, "PCF8574: 8 bit IO expander" },
  43.     { 0x70, 0x7E, "PCF8574A: 8 bit IO expander" },
  44.     { 0x90, 0x9E, "PCF8591: 8 bit DA/AD converter" },
  45.     { 0x70, 0x76, "SAA1064: LED driver 2-4 × 8" },
  46.     { 0x70, 0x72, "PCF8576: LCD driver 1-4 × 40" },
  47.     { 0x74, 0x74, "PCF8577: LCD driver 1-2 × 32" },
  48.     { 0x76, 0x76, "PCF8577A: LCD driver 1-2 × 32" },
  49.     { 0x7C, 0x7E, "PCF8566: LCD driver 1-4 × 24" },
  50.     { 0x78, 0x7A, "PCF8578: LCD dot matrix driver 32×8, 24×16, 16×24 or 8×32,\n"
  51.                 "    possibly with one or more PCF8579 (40 extra columns)" },
  52.     { 0xA0, 0xAE, "PCF8570/PCF8571: 256/128 byte SRAM" },
  53.     { 0xA0, 0xAE, "PCF8581/PCF8582: 256/128 byte EEPROM" },
  54.     { 0xB0, 0xBE, "PCF8570C: 256 byte SRAM" },
  55.     { 0xD0, 0xD6, "PCF8573: clock/calendar" },
  56.     { 0xA0, 0xA2, "PCF8583: clock/calendar and 256 byte SRAM" },
  57.     { 0x80, 0x86, "SAA1300: power output 5 × 85 mA" },
  58.     { 0x88, 0x88, "TDA8442: DAC & switch for color decoder" },
  59.     { 0x90, 0x9E, "TDA8440: AV input selector" },
  60.     { 0x40, 0x4E, "TDA8444: 8 × 6 bit D/A converter" },
  61.     { 0x48, 0x4A, "PCD3311/PCD3312: DTMF/modem/musical tone generator" }
  62.     };
  63.  
  64.  
  65. void identify( UBYTE addr )
  66. /* Tries its best to "identify" a chip address, but most I²C addresses
  67.  * are ambiguous.
  68.  */
  69.     {
  70.     int i;
  71.  
  72.     printf( ", might be:\n" );
  73.     for( i = 0; i < (sizeof chiptab / sizeof chiptab[0]); i++ )
  74.         if( addr >= chiptab[i].lower_addr && addr <= chiptab[i].upper_addr )
  75.             printf( "%s\n", chiptab[i].description );
  76.     }
  77.  
  78.  
  79. int maxerror;           /* will be used to create the return value */
  80.  
  81. int report( ULONG code )
  82. /* analyze an i2clib return code, returns TRUE if it indicates an error */
  83.     {
  84.     static ULONG lastcode = 0;
  85.     STRPTR s;
  86.  
  87.     if( code & 0xFF )   /* indicates OK */
  88.         return FALSE;
  89.     else
  90.         {
  91.         if( code != lastcode )
  92.             {
  93.             lastcode = code;
  94.             if( (code >> 8) > I2C_NO_REPLY )
  95.                 {
  96.                 printf( "I²C bus: error 0x%06lx, %s\n", code, I2CErrText( code ) );
  97.                 s = GetI2COpponent();
  98.                 if( s != NULL )
  99.                     printf("\"%s\" has got our hardware\n", s);
  100.                 if( ((code >> 8) & 0xff) == I2C_HARDW_BUSY )
  101.                     maxerror = 10;
  102.                 else
  103.                     maxerror = 15;  /* serious hardware problem */
  104.                 }
  105.             }
  106.         return TRUE;
  107.         }
  108.     }
  109.  
  110.  
  111. int scan( int verbose )
  112. /* Return value of scan() is the one that the program itself should return, */
  113. /* as explained at the top of this file. */
  114.     {
  115.     int rd=0, wr=0, i;
  116.     char dummy;
  117.     int count=0;
  118.  
  119.     maxerror = 0;
  120.     for( i=0; i<128; i++ )
  121.         {
  122.         wr = !report( SendI2C(2*i, 0, &dummy) );
  123.         rd = !report( ReceiveI2C(2*i+1, 1, &dummy) );
  124.         if (rd || wr)
  125.             {
  126.             count++;
  127.             if( verbose )
  128.                 printf("\n");
  129.             printf( "Chip address " );
  130.             if( rd && wr )
  131.                 printf( "0x%02x/0x%02x: R/W", 2*i, 2*i+1 );
  132.             else if ( rd )
  133.                 printf( "0x%02x: R only", 2*i+1 );
  134.             else
  135.                 printf( "0x%02x: W only", 2*i );
  136.             if( verbose )
  137.                 identify( 2*i );
  138.             else
  139.                 printf( "\n" );
  140.             }
  141.         }
  142.     if( maxerror == 0 && count == 0 )
  143.         return 5;               /* indicate "no replies" */
  144.     else
  145.         return maxerror;
  146.     }
  147.  
  148.  
  149.  
  150. int ctrl_c;
  151.  
  152. void intercept( int class )
  153.     {
  154.     ctrl_c = 1;
  155.     }
  156.  
  157. void watcher()
  158.     {
  159.     ULONG calls;
  160.     struct I2C_Base *ib;
  161.     char *types[] =
  162.         {
  163.         "parallel port",
  164.         "serial port",
  165.         "floppy port",
  166.         "expansion board"
  167.         };
  168.  
  169.     /* install a nicer way of handling ^C */
  170.     ctrl_c = 0;
  171.     signal( SIGINT, intercept );
  172.     ib = (struct I2C_Base *)I2C_Base;
  173.     printf( "Hardware implementation: %s. Hit Ctrl-C to exit.\n",
  174.         types[ ib->HwType ] );
  175.     printf( "\e[0 p       %9s %9s %9s %9s %9s %9s\n\n\n\n",
  176.             "Send", "Recv", "Lost", "Unheard", "Overflow", "Errors" );
  177.     while( !ctrl_c )
  178.         {
  179.         printf( "\e[3ACalls: %9ld %9ld %9ld %9ld %9ld %9ld\nBytes: %9ld %9ld\n",
  180.             ib->SendCalls, ib->RecvCalls, ib->Lost, ib->Unheard,
  181.             ib->Overflows, ib->Errors, ib->SendBytes, ib->RecvBytes );
  182.         calls = ib->SendCalls + ib->RecvCalls;
  183.         if( calls == 0 )
  184.             calls = 1;
  185.         printf( "Average: %7ld %9ld %9ld%% %8ld%% %8ld%% %8ld%%\n",
  186.             ib->SendCalls ? ib->SendBytes / ib->SendCalls : 0,
  187.             ib->RecvCalls ? ib->RecvBytes / ib->RecvCalls : 0,
  188.             ib->Lost / calls, ib->Unheard / calls,
  189.             ib->Overflows / calls, ib->Errors / calls );
  190.         }
  191.     printf( "\e[ p" );          /* make cursor visible again */
  192.     signal( SIGINT, SIG_DFL );  /* restore default break handler */
  193.     }
  194.  
  195.  
  196. void help( char *badarg )
  197.     {
  198.     printf( "Illegal option '%s', usage:\n", badarg );
  199.     printf( "  I2CScan [-d<delay>] [-v[erbose]] [-l[ock]] [-w[atch]]\n" );
  200.     }
  201.  
  202.  
  203. void cleanup()
  204.     {
  205.     if( I2C_Base )
  206.         {
  207.         CloseLibrary( I2C_Base );
  208.         I2C_Base = NULL;
  209.         }
  210.     }
  211.  
  212.  
  213. int main( int argc, char *argv[] )
  214.     {
  215.     ULONG busdelay;
  216.     int i, verbose=FALSE, lockit=FALSE, watch=FALSE;
  217.     int result = 0;
  218.  
  219.     atexit( cleanup );   /* make sure library will be closed upon Ctrl-C */
  220.     I2C_Base = OpenLibrary( "i2c.library", 39 );
  221.     if( I2C_Base == NULL )
  222.         {
  223.         printf( "Can't open i2c.library V39+\n" );
  224.         return 20;
  225.         }
  226.     busdelay = SetI2CDelay( I2CDELAY_READONLY );
  227.     for( i=1; i<argc; i++ )
  228.         if( *argv[i] == '-' )
  229.             {
  230.             switch( argv[i][1] )
  231.                 {
  232.                 case 'd': busdelay = atol(argv[i]+2); break;
  233.                 case 'v': verbose = TRUE; break;
  234.                 case 'w': watch = TRUE; break;
  235.                 case 'l': lockit = TRUE; break;
  236.                 default: help(argv[i]); exit( 10 );
  237.                 }
  238.             }
  239.         else
  240.             {
  241.             help( argv[ i ] );
  242.             exit( 10 );
  243.             }
  244.     if( watch )
  245.         {
  246.         if( I2C_Base->lib_Version < 40 )
  247.             {
  248.             printf( "need i2c.library v40+ for this option\n" );
  249.             exit( 20 );
  250.             }
  251.         watcher();
  252.         }
  253.     else if( lockit )
  254.         {
  255.         ShutDownI2C();
  256.         printf( "I²C activity halted, hit <Return> to continue... " );
  257.         getchar();
  258.         BringBackI2C();
  259.         printf("\e[A\e[49Cthanks.\n");
  260.         }
  261.     else
  262.         {
  263.         SetI2CDelay( busdelay );
  264.         printf( "Delay value for I²C bus timing is %ld, ", busdelay );
  265.         printf( "scanning for listeners ...\n" );
  266.         result = scan( verbose );
  267.         }
  268.     cleanup();
  269.  
  270.     return result;
  271.     }
  272.  
  273.